/*
 * File: hsm_api.h
 *
 * Description:
 *
 *
 * Author:
 *
 * Version History:
 *
 * 	2017.06.15
 *
 */

#ifndef _HSM_API_H
#define _HSM_API_H

#include <stdlib.h>
#include <stdio.h>

#define HSM_MECH_ECB            0x1
#define HSM_MECH_CBC            0x2
#define HSM_MECH_MAC            0xA
#define HSM_MECH_CTR            0x5
#define HSM_MECH_OFB            0x4
#define HSM_MECH_CFB            0x3
#define HSM_MECH_GCM            0x6

#define HSM_MECH_SM1_ECB 		0x0011
#define HSM_MECH_SM1_CBC 		0x0012
#define HSM_MECH_SM1_MAC 		0x001A
#define HSM_MECH_SM1_CFB 		0x0013
#define HSM_MECH_SM1_OFB 		0x0014
#define HSM_MECH_SM1_CTR 		0x0015
#define HSM_MECH_SM1_GCM 		0x0016



#define HSM_MECH_SM4_ECB 		0x0041
#define HSM_MECH_SM4_CBC 		0x0042
#define HSM_MECH_SM4_CFB 		0x0043
#define HSM_MECH_SM4_OFB 		0x0044
#define HSM_MECH_SM4_CTR 		0x0045
#define HSM_MECH_SM4_GCM 		0x0046


#define HSM_MECH_SM4_MAC 		0x004A
#define HSM_MECH_SM3_HASH 		0x0030
#define HSM_MECH_SM3_MAC 		0x003A
#define HSM_MECH_SM2_ENC 		0x002B
#define HSM_MECH_SM2_DEC 		0x002C
#define HSM_MECH_SM2_SIGN 		0x002D
#define HSM_MECH_SM2_VERIFY 	0x002E
#define HSM_MECH_SM2_EXCH 		0x002F
#define HSM_MECH_AES_ECB 		0x0061
#define HSM_MECH_AES_CBC 		0x0062
#define HSM_MECH_AES_MAC 		0x006A
#define HSM_MECH_3DES_ECB 		0x0071
#define HSM_MECH_3DES_CBC 		0x0072
#define HSM_MECH_3DES_MAC 		0x007A
#define HSM_MECH_SHA512_HASH 	0x0080
#define HSM_MECH_SHA512_MAC 	0x008A
#define HSM_MECH_SHA256_HASH 	0x00B0
#define HSM_MECH_SHA256_MAC 	0x00BA
#define HSM_MECH_SM1_SM3_HYBRD 	0x0051
#define HSM_MECH_SM4_SM3_HYBRD 	0x0052
#define HSM_MECH_AES_SHA_HYBRD 	0x0053
#define HSM_MECH_RSA1024_NCRT_PRICALC 	0x0095
#define HSM_MECH_RSA2048_NCRT_PRICALC 	0x0096
#define HSM_MECH_RSA4096_NCRT_PRICALC 	0x0097
#define HSM_MECH_RSA1024_PUBCALC 	0x009A
#define HSM_MECH_RSA1024_PRICALC 	0x009B
#define HSM_MECH_RSA2048_PUBCALC 	0x009C
#define HSM_MECH_RSA2048_PRICALC 	0x009D
#define HSM_MECH_RSA4096_PUBCALC 	0x009E
#define HSM_MECH_RSA4096_PRICALC 	0x009F



#define HSM_KEY_SM1 			0x80000000
#define HSM_PUBKEY_SM2 			0x40000000
#define HSM_PRIKEY_SM2 			0x20000000
#define HSM_KEY_SM3 			0x10000000
#define HSM_KEY_SM4 			0x08000000
#define HSM_KEY_AES 			0x04000000
#define HSM_KEY_3DES 			0x02000000
#define HSM_KEY_SHA512 			0x01000000
#define HSM_KEY_SHA256 			0x00020000
#define HSM_PUBKEY_RSA1024 		0x00800000
#define HSM_PRIKEY_RSA1024 		0x00400000
#define HSM_PUBKEY_RSA2048 		0x00200000
#define HSM_PRIKEY_RSA2048 		0x00100000
#define HSM_PUBKEY_RSA4096 		0x00080000
#define HSM_PRIKEY_RSA4096 		0x00040000
#define HSM_KEY_SM1_SM3 		0x90000000
#define HSM_KEY_SM4_SM3 		0x18000000
#define HSM_KEY_AES_SHA 		0x06000000


#define HSM_SM1_BLOCK_LEN 		16
#define HSM_SM1_KEY_LEN 		16
#define HSM_SM1_IV_LEN 			16
#define HSM_SM4_BLOCK_LEN 		16
#define HSM_SM4_KEY_LEN 		16
#define HSM_SM4_IV_LEN 			16
#define HSM_AES_BLOCK_LEN 		16
#define HSM_AES_KEY_LEN 		16
#define HSM_AES_IV_LEN 			16
#define HSM_3DES_BLOCK_LEN 		16
#define HSM_3DES_KEY_LEN 		16
#define HSM_3DES_IV_LEN 		16
#define HSM_SM3_BLOCK_LEN 		64
#define HSM_SM3_KEY_LEN 		64
#define HSM_SM3_IV_LEN 			32
#define HSM_SHA256_BLOCK_LEN    64
#define HSM_SHA256_KEY_LEN      64
#define HSM_SHA256_IV_LEN       32
#define HSM_SHA512_BLOCK_LEN    128
#define HSM_SHA512_KEY_LEN      128
#define HSM_SHA512_IV_LEN       64

#define HSM_SM2_PUBKEY_LEN 		64
#define HSM_SM2_PRIKEY_LEN 		32
#define HSM_SM2_SIGN_DATA_LEN 	32
#define HSM_SM2_SIGNVAL_LEN 	64




#define DATALEN_SM2_ENC_MAX			128
#define DATALEN_SM2_ENC_MIN			1
#define DATALEN_SM2_C1				HSM_SM2_PUBKEY_LEN
#define DATALEN_SM2_C3				HSM_SM3_IV_LEN
#define DATALEN_SM2_CIPHER(msglen)	(msglen+DATALEN_SM2_C1+DATALEN_SM2_C3)
#define DATALEN_SM2_MSG(cipherlen)	(cipherlen-DATALEN_SM2_C1-DATALEN_SM2_C3)
#define DATALEN_SM2_DEC_MAX			DATALEN_SM2_CIPHER(DATALEN_SM2_ENC_MAX)
#define DATALEN_SM2_DEC_MIN			DATALEN_SM2_CIPHER(DATALEN_SM2_ENC_MIN)
#define DATALEN_SM2_SIGN			32
#define SIGNLEN_SM2					64
         

#define HSM_AUTH_MODE_PIN               0
#define HSM_AUTH_MODE_USBKEY            1
#define HSM_AUTH_MODE_USBKEY_PIN        2

#define HSM_ROLE_MAINT    0 //Maintenance 
#define HSM_ROLE_CO       1 //CryptoOfficer 
#define HSM_ROLE_USER     2 //User

#pragma pack(1)
typedef struct _HSM_DEVICE_INFO
{
    unsigned int uiFirmwareVer[2];	//RO
    unsigned int uiSoftwareVer;
    unsigned char ucSN[16];

    unsigned int uiBufferSize;	//RO

    unsigned int uiSymmCoKeyCnt;
    unsigned int uiSymmUserKeyCnt;
    unsigned int uiECCCoKeyCnt;
    unsigned int uiECCUserKeyCnt;
    unsigned int uiMiscCoKeyCnt;
    unsigned int uiMiscUserKeyCnt;
    unsigned int uiUserSessionCnt;
    unsigned int uiSymmKeyCntPerSession;
    unsigned int uiECCKeyCntPerSession;
    unsigned int uiMiscKeyCntPerSession;
}HSM_DEVICE_INFO, *PHSM_DEVICE_INFO;

typedef struct _HSM_DEVICE_INFO_EXT
{
    unsigned int uiFirmwareVer[2];
    unsigned int uiSoftwareVer;
    unsigned char ucSN[16];
    unsigned int uiBufferSize;
    unsigned int uiSymmCoKeyCnt;
    unsigned int uiSymmUserKeyCnt;
    unsigned int uiECCCoKeyCnt;
    unsigned int uiECCUserKeyCnt;
    unsigned int uiMiscCoKeyCnt;
    unsigned int uiMiscUserKeyCnt;
    unsigned int uiUserSessionCnt;
    unsigned int uiSymmKeyCntPerSession;
    unsigned int uiECCKeyCntPerSession;
    unsigned int uiMiscKeyCntPerSession;
    /*different from hsm_device_info**/
    unsigned int uiRSAKeyCoKeyCnt;
    unsigned int uiRSAKeyUserKeyCnt;
    unsigned int uiOther1KeyCoKeyCnt;
    unsigned int uiOther1KeyUserKeyCnt;
    unsigned int uiRSAKeyCntPerSession;
    unsigned int uiOther1KeyCntPerSession;
} HSM_DEVICE_INFO_EXT, *PHSM_DEVICE_INFO_EXT;


typedef struct _HSM_SESSION_STATUS 
{ 
    unsigned int uiFreeSymmKeyCnt;
    unsigned int uiFreeECCPubKeyCnt;
    unsigned int uiFreeECCPriKeyCnt;
    unsigned int uiFreeMiscKeyCnt;
    unsigned int uiReserved;
}HSM_SESSION_STATUS, *PHSM_SESSION_STATUS;

typedef struct _HSM_SESSION_STATUS_EXT
{
	unsigned int uiFreeSymmKeyCnt;
	unsigned int uiFreeECCPubKeyCnt;
	unsigned int uiFreeECCPriKeyCnt;
	unsigned int uiFreeMiscKeyCnt;
	unsigned int Rsvd;
  /*different from user_session_status*/
	unsigned int uiFreeRSAPubKeyCnt;
	unsigned int uiFreeRSAPriKeyCnt;
	unsigned int uiFreeOther1Cnt;
	unsigned int uiOther1Rsvd;
}HSM_SESSION_STATUS_EXT, *PHSM_SESSION_STATUS_EXT;



typedef struct _HSM_DEVICE_STATUS
{
    unsigned int uiRoleStatus;
    unsigned int uiFreeBufferSize;
    unsigned int uiFreeUserSessionCnt; 
}HSM_DEVICE_STATUS, *PHSM_DEVICE_STATUS;

typedef struct _HSM_SESSION 
{
    void* hHSM;
    unsigned int uiID;
    unsigned char ucToken[16]; 
}HSM_SESSION, *PHSM_SESSION;

typedef struct _HSM_MECHANISM
{
    unsigned short wMechType;
    unsigned char* pucParm;
    unsigned short wParmLen;
    unsigned int uiReserved;
}HSM_MECHANISM, *PHSM_MECHANISM;

#define HSM_RSA_MAX_BITS	4096
#define HSM_RSA_MAX_LEN		512
#define HSM_RSA_MAX_PLEN	256

#define HSM_RSA_E_LEN       16


typedef struct _HSM_RSA_PUBKEY
{
    unsigned int bits;
    unsigned char m[HSM_RSA_MAX_LEN];
    unsigned char e[HSM_RSA_E_LEN];
    unsigned char Rsvd[12];
} HSM_RSA_PUBKEY, *PHSM_RSA_PUBKEY;

typedef struct _HSM_RSA_PRIKEY
{
    unsigned int bits;
    unsigned char m[HSM_RSA_MAX_LEN];
    unsigned char e[HSM_RSA_E_LEN];
    unsigned char d[HSM_RSA_MAX_LEN];
    unsigned char prime[2][HSM_RSA_MAX_PLEN];
    unsigned char pexp[2][HSM_RSA_MAX_PLEN];
    unsigned char coef[HSM_RSA_MAX_PLEN];
    unsigned char Rsvd[12];
} HSM_RSA_PRIKEY, *PHSM_RSA_PRIKEY;

#pragma pack()

#define MAX_ALGO_NUM				64

unsigned int HSM_OpenDevice(unsigned int uiIndex, void** phHSM);
unsigned int HSM_CloseDevice(void* hHSM);
unsigned int HSM_SelfTest(void* hHSM, unsigned int* puiResult);
unsigned int HSM_GetDeviceInfo(void* hHSM, HSM_DEVICE_INFO* pInfo);
unsigned int HSM_SetDestFlag(void* hHSM, unsigned int uiDestFlag);
unsigned int HSM_GetDestFlag(void* hHSM, unsigned int *puiDestFlag);
unsigned int HSM_GetDeviceStatus(void* hHSM, HSM_DEVICE_STATUS* pStatus);
unsigned int HSM_CreateFile(void* hHSM, unsigned char *pucFileName, unsigned int uiNameLen, unsigned int uiFileSize);
unsigned int HSM_ReadFile(void* hHSM, unsigned char *pucFileName, unsigned int uiNameLen, unsigned int uiOffset, unsigned int *puiFileLength, unsigned char *pucBuffer);
unsigned int HSM_WriteFile(void* hHSM, unsigned char *pucFileName, unsigned int uiNameLen, unsigned int uiOffset,  unsigned int uiFileLength,  unsigned char *pucBuffer);
unsigned int HSM_DeleteFile(void* hHSM, unsigned char *pucFileName, unsigned int uiNameLen);
unsigned int HSM_FormatFS(void* hHSM);
unsigned int HSM_GenRandom(void* hHSM, unsigned int* puiDataLen, unsigned char* pucData);
unsigned int HSM_Dump_Supported_Algo(void* hHSM);
unsigned int HSM_C_GenKey(void* hHSM, unsigned int uiKeyType, unsigned char* pucKey, unsigned short* pwKeyLen);
unsigned int HSM_C_GenKeyPair(void* hHSM,unsigned int uiKeyType, unsigned char* pucPubKey, unsigned short* pwPubKeyLen, unsigned char* pucPriKey, unsigned short* pwPriKeyLen);
unsigned int HSM_C_GenKeyPair_Ext(void* hHSM,unsigned int uiKeyType, unsigned char* pucPubKey, unsigned short* pwPubKeyLen, unsigned char* pucPriKey, unsigned short* pwPriKeyLen);
unsigned int HSM_C_Encrypt(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucKey, unsigned short wKeyLen, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_C_Decrypt(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucKey, unsigned short wKeyLen, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_C_Hash(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_C_Mac(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucKey, unsigned short wKeyLen, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_C_HMac(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucKey, unsigned short wKeyLen, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_C_ECCEncrypt(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucPubKey, unsigned short wPubKeyLen, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_C_ECCDecrypt(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucPriKey, unsigned short wPriKeyLen, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_C_ECCSign(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucPriKey, unsigned short wPriKeyLen, unsigned char* pucData, unsigned int uiDataLen, unsigned char* pucSignature, unsigned int*puiSignatureLen);
unsigned int HSM_C_ECCVerify(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucPubKey, unsigned short wPubKeyLen, unsigned char* pucData, unsigned int uiDataLen, unsigned char* pucSignature, unsigned int uiSignatureLen);
unsigned int HSM_C_Encrypt_HMAC(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucKey, unsigned short wKeyLen, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned int uiOffSet, unsigned int uiPlainLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen, unsigned char *pucHMac, unsigned int *puiHMacLen);
unsigned int HSM_C_HMAC_Decrypt(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucKey, unsigned short wKeyLen, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned int uiOffSet, unsigned int uiCipherLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen, unsigned char *pucHMac, unsigned int *puiHMacLen);
unsigned int HSM_DataPadding(unsigned short wMechType, unsigned int* puiPara, unsigned char* pucPadData, unsigned int *puiPadDataLen);
unsigned int HSM_C_ECCAgreementKey(void* hHSM, unsigned char ucSponsorFlag, unsigned char* pucLocalHash, unsigned char* pucRemoteHash, unsigned char* pucLocalPriKey, unsigned char* pucLocalTempPriKey, unsigned char* pucRemotePubKey, unsigned char* pucRemoteTempPubKey, unsigned char* pucKey, unsigned int* puiKeyLen);
unsigned int HSM_C_ECCAgreementKey_ex(void* hHSM, unsigned char ucSponsorFlag, unsigned char* pucLocalHash, unsigned char* pucRemoteHash, unsigned char* pucLocalPriKey, unsigned char* pucLocalTempPriKey, unsigned char* pucRemotePubKey, unsigned char* pucRemoteTempPubKey, unsigned char* pucKey, unsigned int* puiKeyLen, unsigned char *S1, unsigned char *SA);

unsigned int HSM_OpenSession(void *hHSM, unsigned short wRole, unsigned char *pucPIN, unsigned short wPINLen, unsigned short *pwLeftTryCnt, PHSM_SESSION pstSession);
unsigned int HSM_CloseSession(PHSM_SESSION pstSession);
unsigned int HSM_GetSessionStatus(PHSM_SESSION pstSession, HSM_SESSION_STATUS* pstSessionStatus);

unsigned int HSM_GenKey(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned int *puiKeyID);
unsigned int HSM_GenKeyPair(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned int* puiPubKeyID, unsigned int* puiPriKeyID); 
unsigned int HSM_ImportKey(PHSM_SESSION pstSession, unsigned int uiKeyType, PHSM_MECHANISM pstWrapMech, unsigned int uiWrapKeyID, unsigned char* pucKey, unsigned short wKeyLen, unsigned int* puiKeyID);
unsigned int HSM_ImportPubKey(PHSM_SESSION pstSession, unsigned int uiKeyType,unsigned char* pucKey, unsigned short wKeyLen, unsigned int* puiKeyID); 
unsigned int HSM_ImportPriKey(PHSM_SESSION pstSession, unsigned int uiKeyType,PHSM_MECHANISM pstWrapMech, unsigned int uiWrapKeyID, unsigned char* pucKey, unsigned short wKeyLen, unsigned int* puiKeyID); 
unsigned int HSM_ExportKey(PHSM_SESSION pstSession, unsigned int uiKeyID, PHSM_MECHANISM pstWrapMech, unsigned int uiWrapKeyID, unsigned char* pucKey, unsigned short* pwKeyLen); 
unsigned int HSM_ExportPubKey(PHSM_SESSION pstSession, unsigned int uiKeyID, unsigned char* pucKey, unsigned short*pwKeyLen); 
unsigned int HSM_ExportPriKey(PHSM_SESSION pstSession, unsigned int uiKeyID, PHSM_MECHANISM pstWrapMech, unsigned int uiWrapKeyID, unsigned char* pucKey, unsigned short *pwKeyLen);
unsigned int HSM_DestroyKey(PHSM_SESSION pstSession, unsigned int uiKeyID);

unsigned int HSM_StoreCoKey(PHSM_SESSION pstSession, unsigned int uiKeyID,unsigned int uiIndex);
unsigned int HSM_EnableCoKey(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned int uiIndex, unsigned int* puiKeyID);
unsigned int HSM_DelCoKey(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned int uiIndex);
unsigned int HSM_DelAllCoKey(PHSM_SESSION pstSession);

unsigned int HSM_StoreUserKey(PHSM_SESSION pstSession, unsigned int uiKeyID,unsigned int uiIndex); 
unsigned int HSM_EnableUserKey(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned int uiIndex, unsigned int* puiKeyID); 
unsigned int HSM_DelUserKey(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned int uiIndex);
unsigned int HSM_DelAllUserKey(PHSM_SESSION pstSession);

unsigned int HSM_ECCEncrypt(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiPubKeyID, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen); 
unsigned int HSM_ECCDecrypt(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiPriKeyID, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_ECCSign(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiPriKeyID, unsigned char* pucData, unsigned int uiDataLen, unsigned char* pucSignature, unsigned int *puiSignLen);
unsigned int HSM_ECCVerify(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiPubKeyID, unsigned char* pucData, unsigned int uiDataLen, unsigned char* pucSignature, unsigned int uiSignLen);

unsigned int HSM_ECCGenAgeementData(PHSM_SESSION pstSession, unsigned int uiLocalPubKeyID, unsigned int* puiLocalTempPriKeyID, unsigned char* pucLocalPubKey, unsigned char* pucLocalTempPubKey);
unsigned int HSM_ECCGenAgreementDataAndKey(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned char* pucLocalHash, unsigned char* pucRemoteHash, unsigned int uiLocalPriKeyID, unsigned int uiLocalPubKeyID, unsigned char* pucRemotePubKey, unsigned char* pucRemoteTempPubKey, unsigned char* pucLocalPubKey, unsigned char* pucLocalTempPubKey, unsigned int* puiKeyID);
unsigned int HSM_ECCGenAgreementDataAndKey_ex(PHSM_SESSION pstSession,  unsigned int uiKeyType, unsigned char* pucLocalHash, unsigned char* pucRemoteHash, unsigned int uiLocalPriKeyID, unsigned int uiLocalPubKeyID, unsigned char* pucRemotePubKey, unsigned char* pucRemoteTempPubKey, unsigned char* pucLocalPubKey, unsigned char* pucLocalTempPubKey, unsigned char *SB, unsigned char **ppexchCt);
unsigned int HSM_ECCGenKey(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned char* pucLocalHash, unsigned char* pucRemoteHash, unsigned int uiLocalPriKeyID, unsigned int uiLocalTempPriKeyID, unsigned char* pucRemotePubKey, unsigned char* pucRemoteTempPubKey, unsigned int* puiKeyID);
unsigned int HSM_ECCGenKey_ex(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned char* pucLocalHash, unsigned char* pucRemoteHash, unsigned int uiLocalPriKeyID, unsigned int uiLocalTempPriKeyID, unsigned char* pucRemotePubKey, unsigned char* pucRemoteTempPubKey, unsigned char *SA, unsigned char **ppexchCtx);             

unsigned int HSM_ECC_Exch_Check(PHSM_SESSION pstSession, unsigned char *SA, unsigned char *pexchCtx, unsigned int* puiKeyID);

unsigned int HSM_Encrypt_HMAC(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned int uiOffSet, unsigned int uiPlainLen, unsigned char* pucDataOut, unsigned int* puiDataOutLen, unsigned char* pucHMac, unsigned int *puiHMacLen);
unsigned int HSM_HMAC_Decrypt(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned int uiOffSet, unsigned int uiCipherLen, unsigned char* pucDataOut, unsigned int* puiDataOutLen, unsigned char* pucHMac, unsigned int *puiHMacLen);
 
unsigned int HSM_EncryptInit(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, void** phCtx);
unsigned int HSM_EncryptUpdate(PHSM_SESSION pstSession, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_EncryptFinal(PHSM_SESSION pstSession, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_DecryptInit(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, void** phCtx); 
unsigned int HSM_DecryptUpdate(PHSM_SESSION pstSession, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_DecryptFinal(PHSM_SESSION pstSession, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_Encrypt(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen); 
unsigned int HSM_Decrypt(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_HashInit(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, void** phCtx);
unsigned int HSM_HashUpdate(PHSM_SESSION pstSession, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen);
unsigned int HSM_HashFinal(PHSM_SESSION pstSession, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_Hash(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_MacInit(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, void** phCtx);
unsigned int HSM_MacUpdate(PHSM_SESSION pstSession, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen);
unsigned int HSM_MacFinal(PHSM_SESSION pstSession, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_Mac(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen); 
unsigned int HSM_HMac(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);

unsigned int HSM_LoadPromCode(void* hHSM, unsigned char* pucFpgaFirmware, unsigned int uiFpgaFirmwareLen, unsigned short usPackIndex, unsigned short usEOPFlag);
unsigned int HSM_CommTest(void* hHSM, unsigned int uiDataInLen, unsigned char *pucDataIn, unsigned char* pucDataOut, unsigned int *puiDataOutLen);

unsigned int HSM_InitMaint(void* hHSM, unsigned short wMode, unsigned char* pucPIN, unsigned short wPINLen);
unsigned int HSM_ChangeMaintPIN(void* hHSM, unsigned char* pucOldPIN, unsigned short wOldPINLen, unsigned char* pucPIN, unsigned short wPINLen, unsigned short* pwLeftTryCnt);
unsigned int HSM_InitCo(void* hHSM, unsigned short wMode, unsigned char* pucPIN, unsigned short wPINLen); 
unsigned int HSM_ChangeCoPIN(void* hHSM, unsigned char* pucOldPIN, unsigned short wOldPINLen, unsigned char* pucPIN, unsigned short wPINLen, unsigned short* pwLeftTryCnt); 
unsigned int HSM_ChangeUserPIN(void* hHSM, unsigned char* pucOldPIN, unsigned short wOldPINLen, unsigned char* pucPIN, unsigned short wPINLen, unsigned short* pwLeftTryCnt);
unsigned int HSM_DelMaint(PHSM_SESSION pstSession);
unsigned int HSM_GetDeviceLog(PHSM_SESSION pstSession, unsigned short wLogNum, unsigned char* pucLog, unsigned short* pwLogLen); 
unsigned int HSM_DelCo(PHSM_SESSION pstSession);
unsigned int HSM_InitUser(PHSM_SESSION pstSession, unsigned short wMode, unsigned char* pucPIN, unsigned short wPINLen); 
unsigned int HSM_CloseAllUserSession(PHSM_SESSION pstSession);

unsigned int HSM_C_HMacInit(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucKey, unsigned short wKeyLen, void** phCtx);
unsigned int HSM_C_HMacUpdate(void* hHSM, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen);
unsigned int HSM_C_HMacFinal(void* hHSM, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);

unsigned int HSM_HMacInit(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, void** phCtx);
unsigned int HSM_HMacUpdate(PHSM_SESSION pstSession, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen);
unsigned int HSM_HMacFinal(PHSM_SESSION pstSession, void* hCtx, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen); 

unsigned int HSM_RSA_PK_Calc(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_RSA_SK_Calc(PHSM_SESSION pstSession, PHSM_MECHANISM pstMech, unsigned int uiKeyID, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_C_RSA_PK_Calc(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucKey, unsigned short wKeyLen, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);
unsigned int HSM_C_RSA_SK_Calc(void* hHSM, PHSM_MECHANISM pstMech, unsigned char* pucKey, unsigned short wKeyLen, unsigned char* pucDataIn, unsigned int uiDataInLen, unsigned char* pucDataOut, unsigned int *puiDataOutLen);

unsigned int print_hsm_supported_algo(void* hHSM);

unsigned int HSM_C_GetPubKey(void* hHSM, unsigned int uiPubKeyType,
            unsigned char * ucPriKey, unsigned int uiPriKeyLen, 
            unsigned char *ucPubKey, unsigned int *puiPubKeyLen);

unsigned int HSM_GetPubKey(PHSM_SESSION pstSession, unsigned int uiPubKeyType, 
            unsigned int uiPriKeyID, unsigned char *ucPubKey, unsigned int *puiPubKeyLen);

unsigned int HSM_GetDeviceInfo_Ext(void* hHSM, HSM_DEVICE_INFO_EXT* pInfo);
unsigned int HSM_GetSessionStatus_Ext(PHSM_SESSION pstSession, HSM_SESSION_STATUS_EXT* pstSessionStatus);

const char * GetAPIVersion();

unsigned int HSM_GenUserKey(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned int uiIndex);

unsigned int HSM_ImportUserKeyPair(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned int uiIndex, \
                                unsigned char *ucPubKey, unsigned short PKLen, unsigned char *ucPriKey, unsigned short SKLen);
unsigned int HSM_ImportUserKey(PHSM_SESSION pstSession, unsigned int uiKeyType, unsigned int uiIndex, \
                                unsigned char *ucKey, unsigned short KeyLen);

unsigned int HSM_ExportCfg(void *hHSM, unsigned char *pFileName, unsigned int uiFileNameLen, unsigned char *pFileData, unsigned int *puiFileDataLen);

#define ERR_LEVEL_DRV			0x01000000
#define ERR_LEVEL_CMD_DEV		0x02000000
#define ERR_LEVEL_CMD_HOST		0x04000000
#define ERR_LEVEL_API_SDF       0x06000000
#define ERR_DRV(_err_no)        ((u32)(ERR_LEVEL_DRV + _err_no))
#define ERR_CMD_HOST(_err_no)   ((u32)(ERR_LEVEL_CMD_HOST + _err_no))
#define ERR_CMD_DEV(_err_no)    ((u32)(ERR_LEVEL_CMD_DEV + _err_no))
#define ERR_API_SDF(_err_no)    ((u32)(ERR_LEVEL_API_SDF + _err_no))

/*
    host error for input parameter checking
*/

#define ERR_OK		 0
#define	EPERM		 1	/* Operation not permitted */
#define	ENOENT		 2	/* No such file or directory */
#define	ESRCH		 3	/* No such process */
#define	EINTR		 4	/* Interrupted system call */
#define	ENXIO		 6	/* No such device or address */
#define	E2BIG		 7	/* Argument list too long */
#define	ENOEXEC		 8	/* Exec format error */
#define	EBADF		 9	/* Bad file number */
#define	EAGAIN		11	/* Try again */
#define	ENOMEM		12	/* Out of memory */
#define	EACCES		13	/* Permission denied */
#define	EFAULT		14	/* Bad address */
#define	EBUSY		16	/* Device or resource busy */
#define	EEXIST		17	/* File exists */
#define	ENODEV		19	/* No such device */
#define	EINVAL		22	/* Invalid argument */
#define	ENFILE		23	/* File table overflow */
#define	ENOTTY		25	/* Not a typewriter */
#define	ETXTBSY		26	/* Text file busy */
#define	EFBIG		27	/* File too large */
#define	ENOSPC		28	/* No space left on device */
#define	ESPIPE		29	/* Illegal seek */



#define HSM_EMAX		57

#define HSM_EPERM       (ERR_LEVEL_CMD_DEV + 1) /* Operation not permitted */
#define HSM_ENOENT      (ERR_LEVEL_CMD_DEV + 2) /* No such file or directory */
#define HSM_EDEVINIT    (ERR_LEVEL_CMD_DEV + 3) /* device not initialized*/
#define HSM_ENORES      (ERR_LEVEL_CMD_DEV + 4) /* Out of resource*/
#define HSM_EPIN        (ERR_LEVEL_CMD_DEV + 5) /* Error PIN*/
#define HSM_ELOG        (ERR_LEVEL_CMD_DEV + 6) /* Log index invalid */
#define HSM_EBADALGO    (ERR_LEVEL_CMD_DEV + 7) /* Algorithm exception */
#define HSM_EKID        (ERR_LEVEL_CMD_DEV + 8) /*Key ID error*/
#define HSM_EINDEX      (ERR_LEVEL_CMD_DEV + 9) /* Key index error*/
#define HSM_EKEY        (ERR_LEVEL_CMD_DEV + 10)    /* Key invalid */
#define HSM_ETOK        (ERR_LEVEL_CMD_DEV + 11)    /* Key type invalid */
#define HSM_ENOMEM      (ERR_LEVEL_CMD_DEV + 12)    /* Out of memory */
#define HSM_EACCES      (ERR_LEVEL_CMD_DEV + 13)    /* Access denied */
#define HSM_EALGO       (ERR_LEVEL_CMD_DEV + 14)    /* Algorithm not support */
#define HSM_EASYM       (ERR_LEVEL_CMD_DEV + 15)    /* Asymmetric failed */
#define HSM_EFILE       (ERR_LEVEL_CMD_DEV + 16)    /* read/write file failed */
#define HSM_EEXIST      (ERR_LEVEL_CMD_DEV + 17)    /* File exists */
#define HSM_ESROOT      (ERR_LEVEL_CMD_DEV + 18)    /*Access secure root failed */
#define HSM_EPERI       (ERR_LEVEL_CMD_DEV + 19)    /*Access peripheral failed */
#define HSM_EFLAG       (ERR_LEVEL_CMD_DEV + 20)    /*Error flag*/
#define HSM_EREXIST     (ERR_LEVEL_CMD_DEV + 21)    /*Role not exist*/
#define HSM_EINVAL      (ERR_LEVEL_CMD_DEV + 22)    /* Invalid argument */
#define HSM_EOP         (ERR_LEVEL_CMD_DEV + 23)    /* Error High Speed Operation */
#define HSM_EFBIG       (ERR_LEVEL_CMD_DEV + 27)    /* File too large */
#define HSM_ENOSPC      (ERR_LEVEL_CMD_DEV + 28)    /* No space left on device */
#define HSM_ESPIPE      (ERR_LEVEL_CMD_DEV + 29)    /* Illegal seek */
#define HSM_EHMAC       (ERR_LEVEL_CMD_DEV + 30)    /* hmac */
#define HSM_EBADRQC     (ERR_LEVEL_CMD_DEV + 56)    /* Invalid request code */


typedef struct HSM_ERR_string_data_st{
    unsigned int error;
    const char *string;
}HSM_ERR_STRING_DATA;

#define NO_SUCH_ERROR	"This error code may be not returned by hsm"

static HSM_ERR_STRING_DATA HSM_ERR_str_lib[]={
    {0, "Operation successed"},
    {1, "Operation not permitted"},
    {2, "No such file or directory"},
    {3, "device not initialized"},
    {4, "Out of resource"},
    {5, "Error PIN"},
    {6, "Log index invalid"},
    {7, "Algorithm exception"},
    {8, "Key ID error"},
    {9, "Key index error"},
    {10, "Key invalid"},
    {11, "Key type invalid"},
    {12, "Out of memory"},
    {13, "Access denied"},
    {14, "Algorithm not support"},
    {15, "Asymmetric failed"},
    {16, "Read/write file failed"},
    {17, "File exists"},
    {18, "Access secure root failed"},
    {19, "Access peripheral failed"},
    {20, "Error flag"},
    {21, "Role not exist"},
    {22, "Invalid argument"},
    {23, NO_SUCH_ERROR},
    {24, NO_SUCH_ERROR},
    {25, NO_SUCH_ERROR},
    {26, NO_SUCH_ERROR},
    {27, "File too large"},
    {28, "No space left on device"},
    {29, "Illegal seek"},
    {30, NO_SUCH_ERROR},
    {31, NO_SUCH_ERROR},
    {32, NO_SUCH_ERROR},
    {33, NO_SUCH_ERROR},
    {34, NO_SUCH_ERROR},
    {35, NO_SUCH_ERROR},
    {36, NO_SUCH_ERROR},
    {37, NO_SUCH_ERROR},
    {38, NO_SUCH_ERROR},
    {39, NO_SUCH_ERROR},
    {40, NO_SUCH_ERROR},
    {41, NO_SUCH_ERROR},
    {42, NO_SUCH_ERROR},
    {43, NO_SUCH_ERROR},
    {44, NO_SUCH_ERROR},
    {45, NO_SUCH_ERROR},
    {46, NO_SUCH_ERROR},
    {47, NO_SUCH_ERROR},
    {48, NO_SUCH_ERROR},
    {49, NO_SUCH_ERROR},
    {50, NO_SUCH_ERROR},
    {51, NO_SUCH_ERROR},
    {52, NO_SUCH_ERROR},
    {53, NO_SUCH_ERROR},
    {54, NO_SUCH_ERROR},
    {55, NO_SUCH_ERROR},
    {56, "Invalid request code"},
    {57, NO_SUCH_ERROR},
};

#define TRANS_ERR(errno)	(((errno-ERR_LEVEL_CMD_DEV)<HSM_EMAX)?(errno-ERR_LEVEL_CMD_DEV):HSM_EMAX)

static inline void hsm_perror(char *errstring, unsigned int hsm_errcode)
{
    if(hsm_errcode > ERR_LEVEL_DRV && hsm_errcode < ERR_LEVEL_CMD_DEV)
        printf("%s: %s 0x%08x\n", errstring, "the error code is returned by driver", hsm_errcode);
    if(hsm_errcode > ERR_LEVEL_CMD_DEV && hsm_errcode < ERR_LEVEL_CMD_HOST)
        printf("%s: %s\n", errstring, HSM_ERR_str_lib[TRANS_ERR(hsm_errcode)].string);
    if(hsm_errcode > ERR_LEVEL_CMD_HOST)
        printf("%s: %s 0x%08x\n", errstring, "the error code is returned by host when the parameter is checked", hsm_errcode);
}

static inline int hexdump(char *title, unsigned char *buff, int length)
{
    unsigned char *string_tmp = buff;
    int i;
    int count = 0;

    printf("--------------	%s: (start @%p  length 0x%08x)------------------\n", title, buff, length);
    for(i = 0; i< length; i++, count++)
    {
        if(i%16 == 0)
            printf("%08x:	", count);
        printf("%02x ", string_tmp[i]);
        if(i%16 == 15)
            printf("\n");
    }
    printf("\n");
    printf("--------------	%s: (end)------------------\n", title);
    return 0;
}

#endif

